﻿#region Copyright 
/*-------------------------------------------------------------------------
* 命名空间名称/文件名:    SSPivot.Common.Helpers/FileHelper 
* CLR版本:     4.0.30319.42000
* 机器名称:    DESKTOP-NHMLO8A
* 功 能：       N/A
* 类 名：       FileHelper
* 创建时间：  2025/5/22 16:38:51
* 版本号：      v1.0
* 创建人:        xulong
*-------------------------------------------------------------------------*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SSPivot.Common.Helpers
{
    /// <summary>
    /// 文件操作帮助
    /// </summary>
    public class FileHelper
    {
        /// <summary>
        /// Stream转Bytes
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static byte[] StreamToBytes(Stream stream)
        {
            // 设置当前流的位置为流的开始
            stream.Seek(0, SeekOrigin.Begin);
            byte[] bytes = new byte[stream.Length];
            stream.Read(bytes, 0, bytes.Length);
            return bytes;
        }

        /// <summary>
        /// Bytes转Stream
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static Stream BytesToStream(byte[] data)
        {
            return new MemoryStream(data);
        }

        /// <summary>
        /// 保存文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="data"></param>
        public static void Save(string filePath, byte[] data)
        {
            if (data != null && data.Length > 0)
            {
                Directory.CreateDirectory(Path.GetDirectoryName(filePath));
                File.WriteAllBytes(filePath, data);
            }
        }

        /// <summary>
        /// 保存文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="data"></param>
        public static void Save(string filePath, string data)
        {
            Save(filePath, data, Encoding.UTF8);
        }

        /// <summary>
        /// 保存文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="data"></param>
        /// <param name="encoding"></param>
        public static void Save(string filePath, string data, Encoding encoding)
        {
            if (!string.IsNullOrEmpty(data))
            {
                Save(filePath, encoding.GetBytes(data));
            }
        }

        /// <summary>
        /// 文件是否存在
        /// </summary>
        /// <param name="filename">文件名，绝对路径</param>
        /// <returns>是否存在</returns>
        public static bool Exists(string filename)
        {
            return File.Exists(filename);
        }

        /// <summary>
        /// 追加文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="content"></param>
        /// <param name="encoding"></param>
        /// <param name="append"></param>
        public static void Write(string filePath, string content, Encoding encoding = null, bool append = true)
        {
            if (encoding == null) encoding = Encoding.UTF8;
            Directory.CreateDirectory(Path.GetDirectoryName(filePath));
            if (append) File.AppendAllText(filePath, content, encoding);
            else File.WriteAllText(filePath, content, encoding);
        }

        /// <summary>
        /// 读取文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static string Read(string filePath)
        {
            return Read(filePath, Encoding.UTF8);
        }

        /// <summary>
        /// 读取文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="encode"></param>
        /// <returns></returns>
        public static string Read(string filePath, Encoding encode)
        {
            string strRtn = string.Empty;
            try
            {
                strRtn = File.ReadAllText(filePath, encode);
            }
            catch
            { }
            return strRtn;
        }

        /// <summary>
        /// 读取文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static byte[] ReadByte(string filePath)
        {
            return File.ReadAllBytes(filePath);
        }

        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="filePath">文件绝对路径</param>
        public static void Delete(string filePath)
        {
            if (File.Exists(filePath)) File.Delete(filePath);
        }

        /// <summary>
        /// 删除文件夹
        /// </summary>
        /// <param name="folder">文件夹</param>
        public static void DeleteFolder(string folder)
        {
            if (Directory.Exists(folder)) Directory.Delete(folder, true);
        }

        /// <summary>
        /// 是否为合法扩展名
        /// </summary>
        /// <param name="extend"></param>
        /// <param name="allowFileTypes"></param>
        /// <returns></returns>
        public static bool IsAllowExtend(string extend, string allowFileTypes)
        {
            bool blnReturn = false;
            List<string> olsAllowFileType = allowFileTypes.Split<string>(",");
            if (olsAllowFileType.Contains(extend))
            {
                blnReturn = true;
            }
            return blnReturn;
        }

        /// <summary>
        /// 获取文件扩展名
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        static public string GetFileExtendName(string filePath)
        {
            return Path.GetExtension(filePath).Trim('.');
        }

        /// <summary>
        /// 获取文件扩展名
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static string GetFileSimpleName(string filePath)
        {
            return Path.GetFileNameWithoutExtension(filePath);
        }

        /// <summary>
        /// 获取文件名
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static string GetFileName(string filePath)
        {
            return Path.GetFileName(filePath);
        }

        /// <summary>
        /// 获取文件的文件夹
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static string GetFileFolder(string filePath)
        {
            filePath = filePath.Replace("\\", "/");
            if (filePath.LastIndexOf("/") > 0)
                return filePath.Substring(0, filePath.LastIndexOf("/")).ToLower();
            else
                return string.Empty;
        }

        /// <summary>
        /// 获取文件夹的大小
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static decimal GetDirectorySize(string filePath)
        {
            if (!Directory.Exists(filePath))
            {
                return 0;
            }
            DirectoryInfo dirInfo = new DirectoryInfo(filePath);
            decimal odeFileSize = 0;
            foreach (FileSystemInfo fsInfo in dirInfo.GetFileSystemInfos())
            {
                if (fsInfo.Attributes.ToString().ToLower() == "directory")
                {
                    odeFileSize += GetDirectorySize(fsInfo.FullName);
                }
                else
                {
                    FileInfo fiInfo = new FileInfo(fsInfo.FullName);
                    odeFileSize += fiInfo.Length;
                }
            }
            return odeFileSize;
        }

        /// <summary>
        /// 获取文件夹下所有的文件
        /// </summary>
        /// <param name="folder"></param>
        /// <returns></returns>
        public static List<SystemFileDto> GetDirectoryFiles(string folder)
        {
            List<SystemFileDto> olsFiles = new List<SystemFileDto>();
            if (Directory.Exists(folder))
            {
                DirectoryInfo dirInfo = new DirectoryInfo(folder);
                foreach (FileSystemInfo fsInfo in dirInfo.GetFileSystemInfos())
                {
                    SystemFileDto info = new SystemFileDto();
                    info.FileFullName = fsInfo.FullName;
                    info.FileName = GetFileName(fsInfo.FullName);
                    info.FileExtent = GetFileExtendName(info.FileName.ToLower());

                    if ((fsInfo.Attributes & FileAttributes.Directory) > 0)
                    {
                        info.IsFolder = true;
                    }
                    else
                    {
                        info.IsFolder = false;
                    }
                    olsFiles.Add(info);
                }
            }
            return olsFiles;
        }

        /// <summary>
        /// 返回文件大小
        /// </summary>
        /// <param name="size"></param>
        /// <returns></returns>
        public static string FormatFileSize(long size)
        {
            string result = string.Empty;
            long factSize = size;
            if (factSize < 1024.00)
                result = factSize.ToString("F2") + " Byte";
            else if (factSize >= 1024.00 && factSize < 1048576)
                result = (factSize / 1024.00).ToString("F2") + " K";
            else if (factSize >= 1048576 && factSize < 1073741824)
                result = (factSize / 1024.00 / 1024.00).ToString("F2") + " M";
            else if (factSize >= 1073741824)
                result = (factSize / 1024.00 / 1024.00 / 1024.00).ToString("F2") + " G";
            return result;
        }
        /// <summary>
        /// 读文件到byte[]
        /// </summary>
        /// <param name="fileName">硬盘文件路径</param>
        /// <returns></returns>
        public static byte[] ReadFileToByte(string fileName)
        {
            FileStream pFileStream = null;
            byte[] pReadByte = new byte[0];
            try
            {
                pFileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
                BinaryReader r = new BinaryReader(pFileStream);
                r.BaseStream.Seek(0, SeekOrigin.Begin);    //将文件指针设置到文件开
                pReadByte = r.ReadBytes((int)r.BaseStream.Length);
                return pReadByte;
            }
            catch
            {
                return pReadByte;
            }
            finally
            {
                if (pFileStream != null)
                    pFileStream.Close();
            }
        }


        #region FileExists

        /// <summary>
        /// 判断文件是否存在
        /// </summary>
        /// <param name="path">文件绝对路径</param>
        public static bool FileExists(string path)
        {
            return System.IO.File.Exists(path);
        }

        #endregion

        #region DirectoryExists

        /// <summary>
        /// 判断目录是否存在
        /// </summary>
        /// <param name="path">目录绝对路径</param>
        public static bool DirectoryExists(string path)
        {
            return Directory.Exists(path);
        }

        #endregion

        #region CreateDirectory

        /// <summary>
        /// 创建目录
        /// </summary>
        /// <param name="path">文件或目录绝对路径</param>
        public static void CreateDirectory(string path)
        {
            if (path.IsNullOrEmpty())
                return;
            var file = new FileInfo(path);
            var directoryPath = file.Directory?.FullName;
            if (Directory.Exists(directoryPath))
                return;
            Directory.CreateDirectory(directoryPath);
        }

        #endregion

        #region ReadToString

        /// <summary>
        /// 读取文件到字符串
        /// </summary>
        /// <param name="filePath">文件绝对路径</param>
        public static string ReadToString(string filePath)
        {
            return ReadToString(filePath, Encoding.UTF8);
        }

        /// <summary>
        /// 读取文件到字符串
        /// </summary>
        /// <param name="filePath">文件绝对路径</param>
        /// <param name="encoding">字符编码</param>
        public static string ReadToString(string filePath, Encoding encoding)
        {
            if (System.IO.File.Exists(filePath) == false)
                return string.Empty;
            using var reader = new StreamReader(filePath, encoding);
            return reader.ReadToEnd();
        }

        /// <summary>
        /// 读取流转换成字符串
        /// </summary>
        /// <param name="stream">流</param>
        /// <param name="encoding">字符编码</param>
        /// <param name="bufferSize">缓冲区大小</param>
        /// <param name="isCloseStream">读取完成是否释放流，默认为true</param>
        public static string ReadToString(Stream stream, Encoding encoding = null, int bufferSize = 1024 * 2, bool isCloseStream = true)
        {
            if (stream == null)
                return string.Empty;
            encoding ??= Encoding.UTF8;
            if (stream.CanRead == false)
                return string.Empty;
            using var reader = new StreamReader(stream, encoding, true, bufferSize, !isCloseStream);
            if (stream.CanSeek)
                stream.Seek(0, SeekOrigin.Begin);
            var result = reader.ReadToEnd();
            if (stream.CanSeek)
                stream.Seek(0, SeekOrigin.Begin);
            return result;
        }

        #endregion

        #region ReadToStringAsync

        /// <summary>
        /// 读取文件到字符串
        /// </summary>
        /// <param name="filePath">文件绝对路径</param>
        public static async Task<string> ReadToStringAsync(string filePath)
        {
            return await ReadToStringAsync(filePath, Encoding.UTF8);
        }

        /// <summary>
        /// 读取文件到字符串
        /// </summary>
        /// <param name="filePath">文件绝对路径</param>
        /// <param name="encoding">字符编码</param>
        public static async Task<string> ReadToStringAsync(string filePath, Encoding encoding)
        {
            if (System.IO.File.Exists(filePath) == false)
                return string.Empty;
            using var reader = new StreamReader(filePath, encoding);
            return await reader.ReadToEndAsync();
        }

        #endregion

        #region ReadToStream

        /// <summary>
        /// 读取文件流
        /// </summary>
        /// <param name="filePath">文件绝对路径</param>
        public static Stream ReadToStream(string filePath)
        {
            try
            {
                return new FileStream(filePath, FileMode.Open);
            }
            catch
            {
                return null;
            }
        }

        #endregion

        #region ReadToBytes

        /// <summary>
        /// 将文件读取到字节流中
        /// </summary>
        /// <param name="filePath">文件的绝对路径</param>
        public static byte[] ReadToBytes(string filePath)
        {
            if (!System.IO.File.Exists(filePath))
                return null;
            var fileInfo = new FileInfo(filePath);
            using var reader = new BinaryReader(fileInfo.Open(FileMode.Open));
            return reader.ReadBytes((int)fileInfo.Length);
        }

        /// <summary>
        /// 读取流转换成字节数组
        /// </summary>
        /// <param name="stream">流</param>
        public static byte[] ReadToBytes(Stream stream)
        {
            if (stream == null)
                return null;
            if (stream.CanRead == false)
                return null;
            if (stream.CanSeek)
                stream.Seek(0, SeekOrigin.Begin);
            var buffer = new byte[stream.Length];
            stream.Read(buffer, 0, buffer.Length);
            if (stream.CanSeek)
                stream.Seek(0, SeekOrigin.Begin);
            return buffer;
        }

        #endregion

        #region ReadToBytesAsync

        /// <summary>
        /// 读取流转换成字节数组
        /// </summary>
        /// <param name="stream">流</param>
        /// <param name="cancellationToken">取消令牌</param>
        public static async Task<byte[]> ReadToBytesAsync(Stream stream, CancellationToken cancellationToken = default)
        {
            if (stream == null)
                return null;
            if (stream.CanRead == false)
                return null;
            if (stream.CanSeek)
                stream.Seek(0, SeekOrigin.Begin);
            var buffer = new byte[stream.Length];
            await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
            if (stream.CanSeek)
                stream.Seek(0, SeekOrigin.Begin);
            return buffer;
        }

        #endregion

        #region ReadToMemoryStreamAsync

        /// <summary>
        /// 读取文件到内存流
        /// </summary>
        /// <param name="filePath">文件绝对路径</param>
        /// <param name="cancellationToken">取消令牌</param>
        public static async Task<MemoryStream> ReadToMemoryStreamAsync(string filePath, CancellationToken cancellationToken = default)
        {
            try
            {
                if (FileExists(filePath) == false)
                    return null;
                var memoryStream = new MemoryStream();
                await using var stream = new FileStream(filePath, FileMode.Open);
                await stream.CopyToAsync(memoryStream, cancellationToken).ConfigureAwait(false);
                return memoryStream;
            }
            catch
            {
                return null;
            }
        }

        #endregion

        #region Write

        /// <summary>
        /// 将字符串写入文件
        /// </summary>
        /// <param name="filePath">文件绝对路径</param>
        /// <param name="content">内容</param>
        public static void Write(string filePath, string content)
        {
            if (content.IsNullOrEmpty())
                return;
            Write(filePath, content.ToByteArray());
        }

        /// <summary>
        /// 将流写入文件
        /// </summary>
        /// <param name="filePath">文件绝对路径</param>
        /// <param name="content">内容</param>
        public static void Write(string filePath, Stream content)
        {
            if (content == null)
                return;
            using (content)
            {
                var bytes = content.ToBytes();
                Write(filePath, bytes);
            }
        }

        /// <summary>
        /// 将字节流写入文件
        /// </summary>
        /// <param name="filePath">文件绝对路径</param>
        /// <param name="content">内容</param>
        public static void Write(string filePath, byte[] content)
        {
            if (string.IsNullOrWhiteSpace(filePath))
                return;
            if (content == null)
                return;
            CreateDirectory(filePath);
            System.IO.File.WriteAllBytes(filePath, content);
        }

        #endregion

        #region WriteAsync

        /// <summary>
        /// 将字符串写入文件
        /// </summary>
        /// <param name="filePath">文件绝对路径</param>
        /// <param name="content">内容</param>
        /// <param name="cancellationToken">取消令牌</param>
        public static async Task WriteAsync(string filePath, string content, CancellationToken cancellationToken = default)
        {
            if (content.IsNullOrEmpty())
                return;
            await WriteAsync(filePath, content.ToByteArray(), cancellationToken);
        }

        /// <summary>
        /// 将流写入文件
        /// </summary>
        /// <param name="filePath">文件绝对路径</param>
        /// <param name="content">内容</param>
        /// <param name="cancellationToken">取消令牌</param>
        public static async Task WriteAsync(string filePath, Stream content, CancellationToken cancellationToken = default)
        {
            if (content == null)
                return;
            await using (content)
            {
                var bytes = await ToBytesAsync(content, cancellationToken);
                await WriteAsync(filePath, bytes, cancellationToken);
            }
        }

        /// <summary>
        /// 将字节流写入文件
        /// </summary>
        /// <param name="filePath">文件绝对路径</param>
        /// <param name="content">内容</param>
        /// <param name="cancellationToken">取消令牌</param>
        public static async Task WriteAsync(string filePath, byte[] content, CancellationToken cancellationToken = default)
        {
            if (string.IsNullOrWhiteSpace(filePath))
                return;
            if (content == null)
                return;
            CreateDirectory(filePath);
            await System.IO.File.WriteAllBytesAsync(filePath, content, cancellationToken);
        }

        #endregion

        #region Delete

        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="filePaths">文件绝对路径集合</param>
        public static void Delete(IEnumerable<string> filePaths)
        {
            foreach (var filePath in filePaths)
                Delete(filePath);
        }

        #endregion

        #region GetAllFiles

        /// <summary>
        /// 获取全部文件,包括所有子目录
        /// </summary>
        /// <param name="path">目录路径</param>
        /// <param name="searchPattern">搜索模式</param>
        public static List<FileInfo> GetAllFiles(string path, string searchPattern)
        {
            return Directory.GetFiles(path, searchPattern, SearchOption.AllDirectories)
                .Select(filePath => new FileInfo(filePath)).ToList();
        }

        #endregion

        #region Copy

        /// <summary>
        /// 复制文件
        /// </summary>
        /// <param name="sourceFilePath">源文件绝对路径</param>
        /// <param name="destinationFilePath">目标文件绝对路径</param>
        /// <param name="overwrite">目标文件存在时是否覆盖,默认值: false</param>
        public static void Copy(string sourceFilePath, string destinationFilePath, bool overwrite = false)
        {
            if (sourceFilePath.IsNullOrEmpty() || destinationFilePath.IsNullOrEmpty())
                return;
            if (FileExists(sourceFilePath) == false)
                return;
            CreateDirectory(destinationFilePath);
            System.IO.File.Copy(sourceFilePath, destinationFilePath, overwrite);
        }

        #endregion

        #region Move

        /// <summary>
        /// 移动文件
        /// </summary>
        /// <param name="sourceFilePath">源文件绝对路径</param>
        /// <param name="destinationFilePath">目标文件绝对路径</param>
        /// <param name="overwrite">目标文件存在时是否覆盖,默认值: false</param>
        public static void Move(string sourceFilePath, string destinationFilePath, bool overwrite = false)
        {
            if (sourceFilePath.IsNullOrEmpty() || destinationFilePath.IsNullOrEmpty())
                return;
            if (FileExists(sourceFilePath) == false)
                return;
            CreateDirectory(destinationFilePath);
            System.IO.File.Move(sourceFilePath, destinationFilePath, overwrite);
        }

        #endregion
        #region ToBytesAsync

        /// <summary>
        /// 流转换为字节数组
        /// </summary>
        /// <param name="stream">流</param>
        /// <param name="cancellationToken">取消令牌</param>
        public static async Task<byte[]> ToBytesAsync(Stream stream, CancellationToken cancellationToken = default)
        {
            stream.Seek(0, SeekOrigin.Begin);
            var buffer = new byte[stream.Length];
            await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
            return buffer;
        }

        #endregion


    }
}